#include "reactor_msgsocket.h"
#include "databasemagr.h"
#include "command.h"
#include "config.h"

#include <QDebug>
#include <QDataStream>
#include <QApplication>
#include <QFileInfo>
#include "threadpool.h"

Reactor_MsgSocket::Reactor_MsgSocket(TcpSocket *socket, QObject *parent) :
    QObject(parent)
{
    m_nId = -1;
    m_socket = socket; ///1. 类似QTcpSocket的使用方式
    ///2. 获取分配的TcpSocket，并绑定回调获取数据的函数
    m_socket->createRecvCallback(std::bind(&Reactor_MsgSocket::recvCallback, this, std::placeholders::_1));
}
///3. TcpSocket需要读取数据时的回调函数
void Reactor_MsgSocket::recvCallback(char *msg)
{
    m_msgQueue.push(msg);
    if(m_socket->m_tdPool != nullptr)
    {
        Task *task = new Task; ///4. 创建新的任务，并绑定回调函数
        task->function = std::bind(&Reactor_MsgSocket::parseTaskCallBack, this);
        m_socket->m_tdPool->addTask(task); ///5. 将任务添加到任务队列中
    }else
    {
        parseTaskCallBack();
    }
}
///6.线程池需要处理的任务回调函数
void Reactor_MsgSocket::parseTaskCallBack(void)
{
    QByteArray reply = m_msgQueue.front();
    m_msgQueue.pop();

    QJsonParseError jsonError;
    // 转化为 JSON 文档
    QJsonDocument doucment = QJsonDocument::fromJson(reply, &jsonError);
    // 解析未发生错误
    if (!doucment.isNull() && (jsonError.error == QJsonParseError::NoError)) {
        // JSON 文档为对象
        if (doucment.isObject()) {
            // 转化为对象
            QJsonObject jsonObj = doucment.object();
            int nType = jsonObj.value("type").toInt();
            QJsonValue dataVal = jsonObj.value("data");

            switch (nType) {
            case Register: parseReister(dataVal); break;
            case Login: parseLogin(dataVal); break;
            case UserOnLine: parseUserOnline(dataVal); break;
            case Logout:
                parseLogout(dataVal);
                emit signalDisConnected();
                break;
            case UpdateHeadPic: parseUpdateUserHead(dataVal); break;
            case AddFriend: parseAddFriend(dataVal); break;
            case AddGroup: parseAddGroup(dataVal); break;
            case CreateGroup: parseCreateGroup(dataVal); break;
            case GetMyFriends: parseGetMyFriend(dataVal); break;
            case GetMyGroups: parseGetMyGroups(dataVal); break;

            case RefreshFriends: parseRefreshFriend(dataVal); break;
            case RefreshGroups: parseRefreshGroups(dataVal); break;

            case SendMsg:
            case SendFile:
            case SendPicture: parseFriendMessages(reply); break;
            case SendGroupMsg: parseGroupMessages(reply); break;
            case SendFace: parseGroupMessages(reply); break;
            case SendFileOk: break;
            case GetFile: emit signalDownloadFile(dataVal); break;
            default:
                break;
            }
        }
    }
}

/**
 * @brief Reactor_MsgSocket::parseLogin
 * 解析登录信息
 * @param reply
 */
void Reactor_MsgSocket::parseLogin(const QJsonValue &dataVal)
{
    // data 的 value 是对象
    if (dataVal.isObject()) {
        QJsonObject dataObj = dataVal.toObject();
        QString strName = dataObj.value("name").toString();
        QString strPwd = dataObj.value("passwd").toString();
        QJsonObject jsonObj = DataBaseMagr::Instance()->CheckUserLogin(strName, strPwd);

        m_nId = jsonObj.value("id").toInt();

        if (m_nId > 0) Q_EMIT signalConnected();
        // 发送查询结果至客户端
        SltSendMessage(Login, jsonObj);;
    }
}

/**
 * @brief Reactor_MsgSocket::parseUserOnline
 * 用户上线
 * @param dataVal
 */
void Reactor_MsgSocket::parseUserOnline(const QJsonValue &dataVal)
{
    // data 的 value 是数组
    if (dataVal.isArray()) {
        QJsonArray jsonArray = dataVal.toArray();
        int nSize = jsonArray.size();
        for (int i = 0; i < nSize; ++i) {
            int nId = jsonArray.at(i).toInt();
            int nStatus = DataBaseMagr::Instance()->GetUserLineStatus(nId);
            // 给在线的好友通报一下状态
            if (OnLine == nStatus) {
                QJsonObject jsonObj;
                jsonObj.insert("id", m_nId);
                jsonObj.insert("text", "online");

                Q_EMIT signalMsgToClient(UserOnLine, nId, jsonObj);
            }
        }
    }

}

/**
 * @brief Reactor_MsgSocket::parseLogin
 * 解析登录信息
 * @param reply
 */
void Reactor_MsgSocket::parseLogout(const QJsonValue &dataVal)
{
    // data 的 value 是对象
    if (dataVal.isObject()) {
        QJsonObject dataObj = dataVal.toObject();

        QJsonArray array = dataObj.value("friends").toArray();
        int nId = dataObj.value("id").toInt();
        int nSize = array.size();

        DataBaseMagr::Instance()->UpdateUserStatus(nId, OffLine);

        for (int i = 0; i < nSize; ++i) {
            nId = array.at(i).toInt();
            int nStatus = DataBaseMagr::Instance()->GetUserLineStatus(nId);
            // 给在线的好友通报一下状态
            if (OnLine == nStatus) {
                QJsonObject jsonObj;
                jsonObj.insert("id", m_nId);
                jsonObj.insert("text", "offline");

                Q_EMIT signalMsgToClient(UserOffLine, nId, jsonObj);
            }
        }
    }
}

/**
 * @brief Reactor_MsgSocket::parseUpdateUserHead
 * 更新用户头像文件
 * @param dataVal
 */
void Reactor_MsgSocket::parseUpdateUserHead(const QJsonValue &dataVal)
{
    // data 的 value 是对象
    if (dataVal.isObject()) {
        QJsonObject dataObj = dataVal.toObject();
        int nId = dataObj.value("id").toInt();
        QString strHead = dataObj.value("head").toString();

        // 更新数据库
        DataBaseMagr::Instance()->UpdateUserHead(nId, strHead);

        // 通知其他在线好友，说我已经修改了头像
        QJsonArray jsonFriends =  dataObj.value("friends").toArray();
        QJsonObject jsonObj;
        // 是我在更新，我要去下载我的头像
        jsonObj.insert("id", nId);
        jsonObj.insert("head", strHead);

        for (int i = 0; i < jsonFriends.size(); i++) {
            nId = jsonFriends.at(i).toInt();
            Q_EMIT signalMsgToClient(UpdateHeadPic, nId, jsonObj);
        }
    }
}

/**
 * @brief Reactor_MsgSocket::parseReister
 * 解析注册信息
 * @param reply
 */
void Reactor_MsgSocket::parseReister(const QJsonValue &dataVal)
{
    // data 的 value 是对象
    if (dataVal.isObject()) {
        QJsonObject dataObj = dataVal.toObject();
        QString strName = dataObj.value("name").toString();
        QString strPwd = dataObj.value("passwd").toString();
        m_nId = DataBaseMagr::Instance()->RegisterUser(strName, strPwd);

        // 返回客户端
        QJsonObject json;
        json.insert("id", m_nId);
        json.insert("name", strName);
        json.insert("passwd", strPwd);

        // 发送查询结果至客户端
        SltSendMessage(Register, json);;
    }
}

/**
 * @brief Reactor_MsgSocket::parseAddFriend
 * 添加好友
 * @param reply
 */
void Reactor_MsgSocket::parseAddFriend(const QJsonValue &dataVal)
{
    // data 的 value 是对象
    if (dataVal.isObject()) {

        QJsonObject dataObj = dataVal.toObject();
        QString strName = dataObj.value("name").toString();
        QJsonObject jsonFriend = DataBaseMagr::Instance()->AddFriend(strName);
        int nId = jsonFriend.value("id").toInt();
        QString strMsg = jsonFriend.value("msg").toString();

        // 发送查询结果至客户端
        SltSendMessage(AddFriend, jsonFriend);

        if (nId < 0) return;

        // 给对方ID发送add请求
        QJsonObject jsonQuery = DataBaseMagr::Instance()->GetUserInfo(m_nId);
        QJsonObject jsonRequest;
        jsonRequest.insert("id", m_nId);
        jsonRequest.insert("name", jsonQuery.value("name").toString());
        jsonRequest.insert("head", jsonQuery.value("head").toString());
        jsonRequest.insert("msg", strMsg.isEmpty() ? "附加消息： 你好！" : strMsg);

        Q_EMIT signalMsgToClient(AddFriendRequist, nId, jsonRequest);
    }
}

/**
 * @brief Reactor_MsgSocket::parseAddGroup
 * 添加群组
 * @param dataVal
 */
void Reactor_MsgSocket::parseAddGroup(const QJsonValue &dataVal)
{
    // data 的 value 是对象
    if (dataVal.isObject()) {
        QJsonObject dataObj = dataVal.toObject();
        int nId = dataObj.value("id").toInt();
        QString strName = dataObj.value("name").toString();
        QJsonObject json = DataBaseMagr::Instance()->AddGroup(nId, strName);

        // 发送查询结果至客户端
        SltSendMessage(AddGroup, json);
    }
}

/**
 * @brief Reactor_MsgSocket::parseCreateGroup
 * 创建群组
 * @param dataVal
 */
void Reactor_MsgSocket::parseCreateGroup(const QJsonValue &dataVal)
{
    // data 的 value 是对象
    if (dataVal.isObject()) {
        QJsonObject dataObj = dataVal.toObject();
        int nId = dataObj.value("id").toInt();
        QString strName = dataObj.value("name").toString();
        QJsonObject json = DataBaseMagr::Instance()->CreateGroup(nId, strName);

        // 发送查询结果至客户端
        SltSendMessage(CreateGroup, json);
    }
}

/**
 * @brief Reactor_MsgSocket::parseGetMyFriend
 * 上线的时候获取我的好友
 * @param dataVal
 */
void Reactor_MsgSocket::parseGetMyFriend(const QJsonValue &dataVal)
{
    QJsonArray jsonArray;
    // data 的 value 是数组
    if (dataVal.isArray())
    {
        QJsonArray array = dataVal.toArray();
        int nSize = array.size();
        // 先添加在线好友，在添加离线好友
        for (int i = 0; i < nSize; ++i)
        {
            int nId = array.at(i).toInt();
            jsonArray.append(DataBaseMagr::Instance()->GetUserStatus(nId));
        }
    }

    this->SltSendMessage(GetMyFriends, jsonArray);
}

/**
 * @brief Reactor_MsgSocket::parseGetMyGroups
 * 上线的时候获取我的群组
 * @param dataVal
 */
void Reactor_MsgSocket::parseGetMyGroups(const QJsonValue &dataVal)
{
    QJsonArray jsonArray;
    // data 的 value 是数组
    if (dataVal.isObject()) {
        QJsonObject jsonObj = dataVal.toObject();
        // 群组ID
        int nId = jsonObj.value("id").toInt();
        jsonArray = DataBaseMagr::Instance()->GetGroupUsers(nId);
    }

    this->SltSendMessage(GetMyGroups, jsonArray);
}

/**
 * @brief Reactor_MsgSocket::parseRefreshFriend
 * @param dataVal
 */
void Reactor_MsgSocket::parseRefreshFriend(const QJsonValue &dataVal)
{
    QJsonArray jsonArray;
    // data 的 value 是数组
    if (dataVal.isArray()) {
        QJsonArray array = dataVal.toArray();
        int nSize = array.size();
        for (int i = 0; i < nSize; ++i) {
            int nId = array.at(i).toInt();
            jsonArray.append(DataBaseMagr::Instance()->GetUserStatus(nId));
        }
    }

    this->SltSendMessage(RefreshFriends, jsonArray);
}

/**
 * @brief Reactor_MsgSocket::parseRefreshGroups
 * 刷新当前群组里面的好友信息
 * @param dataVal
 */
void Reactor_MsgSocket::parseRefreshGroups(const QJsonValue &dataVal)
{
    QJsonArray jsonArray;
    // data 的 value 是数组
    if (dataVal.isObject()) {
        QJsonObject jsonObj = dataVal.toObject();
        // 群组ID
        int nId = jsonObj.value("id").toInt();
        jsonArray = DataBaseMagr::Instance()->GetGroupUsers(nId);
    }

    this->SltSendMessage(RefreshGroups, jsonArray);
}

/**
 * @brief Reactor_MsgSocket::parseMessages
 * 解析消息类，包括文字、图片、文件等
 * @param reply
 */
void Reactor_MsgSocket::parseFriendMessages(const QByteArray &reply)
{
    // 重新组装数据
    QJsonParseError jsonError;
    // 转化为 JSON 文档
    QJsonDocument doucment = QJsonDocument::fromJson(reply, &jsonError);
    // 解析未发生错误
    if (!doucment.isNull() && (jsonError.error == QJsonParseError::NoError)) {
        // JSON 文档为对象
        if (doucment.isObject()) {
            // 转化为对象
            QJsonObject jsonObj = doucment.object();
            int nType = jsonObj.value("type").toInt();
            QJsonValue dataVal = jsonObj.value("data");

            QJsonObject dataObj = dataVal.toObject();
            int nId = dataObj.value("to").toInt();
            Q_EMIT signalMsgToClient(nType, nId, dataObj);
        }
    }
}

/**
 * @brief Reactor_MsgSocket::parseGroupMessages
 * 处理群组消息转发
 * @param reply
 */
void Reactor_MsgSocket::parseGroupMessages(const QByteArray &reply)
{
    // 重新组装数据
    QJsonParseError jsonError;
    // 转化为 JSON 文档
    QJsonDocument doucment = QJsonDocument::fromJson(reply, &jsonError);
    // 解析未发生错误
    if (!doucment.isNull() && (jsonError.error == QJsonParseError::NoError)) {
        // JSON 文档为对象
        if (doucment.isObject()) {
            // 转化为对象
            QJsonObject jsonObj = doucment.object();
            int nType = jsonObj.value("type").toInt();
            QJsonValue dataVal = jsonObj.value("data");

            QJsonObject dataObj = dataVal.toObject();
            // 转发的群组id
            int nGroupId = dataObj.value("to").toInt();
            QString strMsg = dataObj.value("msg").toString();
            // 查询该群组下面的用户，一一转发消息
            QString name = DataBaseMagr::Instance()->GetUserName(m_nId);

            // 查询该群组里面的在线好友
            QJsonArray jsonArr = DataBaseMagr::Instance()->GetGroupUsers(nGroupId);
            if (jsonArr.size() < 2) return;
            for (int i = 1; i < jsonArr.size(); i++) {
                QJsonObject json = jsonArr.at(i).toObject();
                int nStatus = json.value("status").toInt();
                int nUserId = json.value("id").toInt();

                // 只给在线的好友转发消息
                if (OnLine == nStatus && m_nId != nUserId) {
                    // 重组消息
                    QJsonObject jsonMsg;
                    jsonMsg.insert("group", nGroupId);
                    jsonMsg.insert("id", m_nId);
                    jsonMsg.insert("name", name);
                    jsonMsg.insert("to", nUserId);
                    jsonMsg.insert("msg", strMsg);
                    jsonMsg.insert("head", DataBaseMagr::Instance()->GetUserHead(m_nId));

                    Q_EMIT signalMsgToClient(nType, nUserId, jsonMsg);
                }
            }
        }
    }
}

/**
 * @brief Reactor_MsgSocket::SltSendMessage
 * @param type
 * @param json
 */
void Reactor_MsgSocket::SltSendMessage(const quint8 &type, const QJsonValue &jsonVal)
{
//    if (!m_socket->isOpen()) return;

    // 构建 Json 对象
    QJsonObject jsonObj;
    jsonObj.insert("type", type);
    jsonObj.insert("from", m_nId);
    jsonObj.insert("data", jsonVal);

    // 构建 Json 文档
    QJsonDocument document;
    document.setObject(jsonObj);
    m_socket->sendData(document.toJson(QJsonDocument::Compact).toStdString().c_str());
}

int Reactor_MsgSocket::GetUserId() const
{
    return m_nId;
}

void Reactor_MsgSocket::Close()
{
//    m_socket->abort();
}

void Reactor_MsgSocket::SltConnected()
{
    //    Q_EMIT signalConnected();
}

void Reactor_MsgSocket::SltDisconnected()
{
    DataBaseMagr::Instance()->UpdateUserStatus(m_nId, OffLine);
    Q_EMIT signalDisConnected();
}

Reactor_MsgSocket::~Reactor_MsgSocket()
{
    delete m_socket;
}
